
/**********************************************************************************\
** 文件名称: menu.c
** 创建人员: YCG
** 创建日期: 2019-01-19
** 文档描述:
** 版本代号: V0.1
** 版本说明: 初始版本
\********************************************************************************/
#include	"menu.h"
#include "MessageOut.h"
#define  MENU_Printf(fmt,...)   Uprintf(fmt,__VA_ARGS__)
static void Menu_CmdDeal(CmdHead_t* yCmdHead, uint8_t yCmd);

/*******************************************************************************
** 函数名称: Menu_Create
** 功能描述: 创建一个菜单
** 参数说明:
							yName:   [输入] 菜单名字
							yInit:   [输入] 菜单初始化函数
							yUpdate: [输入] 菜单更新函数
							yFree:   [输入] 菜单空载函数
							yResume: [输入] 菜单恢复函数

** 返回说明: yMenuHead: 创建菜单的句柄
** 创建人员: YCG
** 创建日期: 2019-02-25
********************************************************************************/
MenuHead_t* Menu_Create(
    uint8_t* yName,
    void     (*yInit)(MenuHead_t *yMenuHead),
    void     (*yUpdate)(MenuHead_t *yMenuHead),
    void     (*yFree)(MenuHead_t *yMenuHead),
    void     (*yResume)(MyList_t* yList)
)
{
    MenuHead_t *yMenuHead = MyMalloc(sizeof(MenuHead_t));   //获取内存空间

    if(yMenuHead != NULL) {                              //如果成功分配到空间

        ListInit((MyList_t*) yMenuHead);                 //初始化表头部分

        yMenuHead->MainMenu  = yMenuHead;                //主级菜单
        yMenuHead->IndexMenu = yMenuHead;                //当前操作菜单
        yMenuHead->PreMenu   = NULL;                     //没有上级菜单

        yMenuHead->RunState = MENU_NO_Init;              //设置为未初始化

        yMenuHead->Init   = yInit;                       //菜单初始化函数
        yMenuHead->Update = yUpdate;                     //菜单更新函数
        yMenuHead->Free   = yFree;                       //菜单空载函数
        yMenuHead->Resume = yResume;                     //菜单恢复函数

        memcpy(yMenuHead->Name, yName, MENU_NAME_SIZE); //复制菜单名称
        yMenuHead->Name[MENU_NAME_SIZE - 1] = 0;          //将最后一位设为0，保证字符串有结束符

        MENU_Printf("Menu_Create:%s\n\n", yMenuHead->Name);  //调试
    }
    return yMenuHead;
}

/*******************************************************************************
** 函数名称: Menu_CmdCreat
** 功能描述: 为主菜单创建Cmd命令控制对象
** 参数说明: yMenuHead: [输入] 主菜单
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2019-02-25
********************************************************************************/
void Menu_CmdCreat(MenuHead_t* yMenuHead) {
   yMenuHead->Cmd = MyMalloc(sizeof(CmdHead_t));           //获取内存空间
	 Cmd_Init( yMenuHead->Cmd, Menu_CmdDeal);                //初始化CMD控制对象
   yMenuHead->Cmd->Target = yMenuHead ;                    //CMD控制对象与菜单控制头相连
   MENU_CMD_State(yMenuHead) = MENU_CMD_ToMenu;            //CMD控制归属于菜单   
}

/*******************************************************************************
** 函数名称: Menu_AddItem
** 功能描述: 添加菜单项到菜单中
** 参数说明: yMenuItem: [输入] 添加菜单项的菜单句柄
						 yName:     [输入] 菜单项名字
						 yTask:     [输入] 菜单项任务
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2019-02-25
********************************************************************************/
MenuItem_t * Menu_AddItem(MenuHead_t* yMenuHead, uint8_t* yName, void(*yTask)(MenuItem_t *yMenuItem)) {

    MenuItem_t *yMenuItem = MyMalloc(sizeof(MenuItem_t));   //获取内存空间

    if(yMenuItem != NULL) {
        ListItemInit((MyListItem_t*) yMenuItem);    //初始化菜单项头部
        yMenuItem->Value = yMenuHead->ListNum;      //设置菜单项的序号
        yMenuItem->Task = yTask;                    //添加任务函数
        yMenuItem->Menu = NULL;                     //表明此项作为任务，而不作为子菜单

        memcpy(yMenuItem->Name, yName, MENU_NAME_SIZE); //复制菜单项名称
        yMenuItem->Name[MENU_NAME_SIZE - 1] = 0;          //将最后一位设为0，保证字符串有结束符

        ListInsert((MyList_t*)yMenuHead, (MyListItem_t*) yMenuItem);  //将此项插入菜单中

        MENU_Printf("Menu_AddItem:%s\n\n", yMenuItem->Name);  //调试
    }
    return yMenuItem;
}

/*******************************************************************************
** 函数名称: Menu_AddSubMenu
** 功能描述:
** 参数说明: yMenuHead: [输入] 添加菜单的菜单句柄
**			     yName:     [输入] 子菜单的菜单项名字
**			     ySubMenuHead: [输入] 子菜单句柄
** 返回说明: 子菜单的菜单项句柄
** 创建人员: YCG
** 创建日期: 2019-02-25
********************************************************************************/
MenuItem_t * Menu_AddSubMenu(MenuHead_t* yMenuHead, uint8_t* yName, MenuHead_t* ySubMenuHead)
{
    MenuItem_t *yMenuItem = MyMalloc(sizeof(MenuItem_t));   //获取内存空间

    if(yMenuItem != NULL) {
        ListItemInit((MyListItem_t*) yMenuItem);    //初始化菜单项头部
        yMenuItem->Value = yMenuHead->ListNum;      //设置菜单项的序号
        yMenuItem->Task  = NULL;                    //没有任务函数
        yMenuItem->Menu  = ySubMenuHead;            //表明此项为子菜单

			  ySubMenuHead->Cmd= yMenuHead->Cmd;          //子菜单的控制项与主菜单相同
			
        ySubMenuHead->MainMenu = yMenuHead->MainMenu; //设置主菜单
        ySubMenuHead->PreMenu  = yMenuHead;           //设置上级菜单

        memcpy(yMenuItem->Name, yName, MENU_NAME_SIZE); //复制菜单项名称
        yMenuItem->Name[MENU_NAME_SIZE - 1] = 0;          //将最后一位设为0，保证字符串有结束符

        ListInsert((MyList_t*) yMenuHead, (MyListItem_t*) yMenuItem);  //将此项插入菜单中

        MENU_Printf("Menu_AddMenu:%s\n\n", yMenuItem->Name);  //调试
    } else {
        MENU_Printf("Menu_AddMenu:%s Failed\n\n", yName);  //调试
    }
    return yMenuItem;
}


/*******************************************************************************
** 函数名称: Menu_Run
** 功能描述:
** 参数说明: yMenuHead: [输入] 主菜单句柄
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2019-02-25
********************************************************************************/
void Menu_Run(MenuHead_t* yMenuHead) {
    uint8_t yState = yMenuHead->RunState;
    MenuItem_t *yNowMenuItem = NULL;
	
    MENU_Printf("Menu_Run:%s\n\n", yMenuHead->Name);  //调试

    while(yState != MENU_OVER) {    //菜单没有结束运行
			
        yNowMenuItem = (MenuItem_t*)yMenuHead->Index; //获取当前菜单项
        switch (yState)
        {
					
        case MENU_NO_Init:           //初始化
					
            if(yMenuHead->Init != NULL) {       //运行初始化函数
                yMenuHead->Init(yMenuHead);
                MENU_Printf("State %d: MENU_NO_Init\n", yState);  //调试
            }
						
            LIST_TO_HEAD(((MyList_t*)yMenuHead));    //切换到第一项菜单
            yMenuHead->RunState = MENU_Update;       //切换到更新状态
            break;

        case MENU_Update:
            if(yMenuHead->Update != NULL) {       //运行更新函数
                yMenuHead->Update(yMenuHead);        //菜单更新
                MENU_Printf("State %d: MENU_Update\n", yState);  //调试
                MENU_Printf("NowMenu: %s\nNowItem: %s\n", yMenuHead->Name, ((MenuItem_t*)(yMenuHead->Index))->Name); //调试
            }
            yMenuHead->RunState = MENU_RunFree; //切换到空运行状态
            MENU_Printf("State %d: MENU_RunFree\n", yMenuHead->RunState);  //调试
            break;

        case MENU_RunFree:
					
            if(yMenuHead->Free != NULL) {          //运行空载函数      
                yMenuHead->Free(yMenuHead);        //菜单空载运行
            }
						
            if(Cmd_ReadCmd(yMenuHead->Cmd, MENU_CMD_WaitToReturn)) {
                yMenuHead->RunState = MENU_Return;   //切换到返回状态
            }
            break;

        case MENU_RunTask:                        //运行菜单项函数
            if(yNowMenuItem->Task != NULL) {
                yNowMenuItem->Task(yNowMenuItem); //运行菜单对应的任务
                MENU_Printf("State %d: MENU_RunTask\n", yState);  //调试
            }
            break;

        case MENU_GoNext:                  //切换到下级菜单
            yMenuHead->MainMenu->IndexMenu = yNowMenuItem->Menu;  //更新正在运行的菜单
            MENU_Printf("State %d: MENU_GoNext %s\n\n", yState, yNowMenuItem->Menu->Name); //调试
				
            Menu_Run(yNowMenuItem->Menu);           //运行下一级菜单

            yMenuHead->RunState = MENU_Update;      //返回后切换到更新状态
            break;

        case MENU_Return:                  //返回上级菜单
            yMenuHead->RunState = MENU_Update;      //切换到空运行状态,下次运行时
            if(yMenuHead->PreMenu != NULL) {        //不等于空，说明有上级菜单，返回上级菜单
                yMenuHead->MainMenu->IndexMenu = yMenuHead->PreMenu;  // //更新正在运行的菜单
                MENU_Printf("State %d: MENU_Return %s\n\n", yState, yMenuHead->PreMenu->Name); //调试
                return;
            }
            break;

        default:
            break;
        }
        yState = yMenuHead->RunState;  //刷新当前状态
    }
}


/*******************************************************************************
** 函数名称: Menu_CmdDeal
** 功能描述:
** 参数说明: yCmdHead: [输入/出]
**			 yCmd: [输入/出]
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2019-02-25
********************************************************************************/
static void Menu_CmdDeal(CmdHead_t* yCmdHead, uint8_t yCmd) {
    MenuHead_t* yMenuHead = (MenuHead_t*)(yCmdHead->Target);
    MENU_Printf("CmdState: %d\n", MENU_CMD_State(yMenuHead));  //调试
	
    /*****返回命令是全局控制*****/
    if(Cmd_ReadCmd(yMenuHead->Cmd, MENU_CMD_BACK)) {             //返回键  返回菜单选项
        switch(yMenuHead->RunState) {
					
        case MENU_RunTask:
        case MENU_GoNext:
            MENU_CMD_State(yMenuHead) = MENU_CMD_ToMenu;    //将CMD的使用权还给菜单
            yMenuHead->RunState = MENU_Update;              //切换到返回菜单运行态
            break;

        default:
            Cmd_SendCmd(yMenuHead->Cmd, MENU_CMD_WaitToReturn);  //其余状态则等待返回
            break;
        }
    }

    if( MENU_CMD_State(yMenuHead) == MENU_CMD_ToMenu) {
        if(Cmd_ReadCmd(yMenuHead->Cmd, MENU_CMD_OK)) {
            MenuItem_t* yMenuItem = (MenuItem_t*)yMenuHead->Index;  //获取现在的菜单项
            if(yMenuHead->Index != yMenuHead->EndItem) {
                if(yMenuItem->Task != NULL) {
                     MENU_CMD_State(yMenuHead) = MENU_CMD_ToItem;          //将CMD的使用权给任务
                    MENU_Printf("State %d: MENU_RunTask\n", MENU_RunTask);  //调试
                    yMenuHead->RunState = MENU_RunTask;                   //运行菜单项任务
                }

                if(yMenuItem->Menu != NULL) {
                    yMenuHead->RunState = MENU_GoNext;                    //进入下一级菜单
                }
            }
        }
        if(Cmd_ReadCmd(yMenuHead->Cmd, MENU_CMD_UP)) {
            if(yMenuHead->ListNum > 0) {                              //菜单不为空
                LIST_C_TO_PRE(((MyList_t*)yMenuHead));                //切换到上一个，跳过尾地址
                yMenuHead->RunState = MENU_Update;                    //更新一下菜单
            } else {                                                  //菜单是空的

            }
        }

        if(Cmd_ReadCmd(yMenuHead->Cmd, MENU_CMD_DOWM)) {
            if(yMenuHead->ListNum > 0) {                             //菜单不为空
                LIST_C_TO_NEXT(((MyList_t*)yMenuHead));              //切换到下一个
                yMenuHead->RunState = MENU_Update;                   //更新一下菜单
            } else {                                                 //菜单是空的

            }
        }
    }
}
/********************************End of File************************************/



